package metrics

import (
	"github.com/rcrowley/go-metrics"
	"time"
)

type Metrics interface {
	Close()
}

type TimerContext interface {
	Stop()
}

type InnerTimerContext struct {
	TimerContext
	timer metrics.Timer
	start time.Time
}

func (tc *InnerTimerContext) Stop() {
	d := time.Since(tc.start)
	tc.timer.Update(d)
}

func NewInnerTimerContext(timer metrics.Timer) TimerContext {
	return &InnerTimerContext{
		timer: timer,
		start: time.Now(),
	}
}

type BaseMetrics struct {
	Metrics
	BaseName string
	Registry metrics.Registry
}

func (bm *BaseMetrics) NameOf(name string) string {
	return bm.BaseName + name
}

func (bm *BaseMetrics) Counter(name string) metrics.Counter {
	return metrics.NewRegisteredCounter(bm.NameOf(name), bm.Registry)
}

func (bm *BaseMetrics) Histogram(name string) metrics.Histogram {
	return metrics.NewRegisteredHistogram(bm.NameOf(name), bm.Registry, metrics.NewUniformSample(1024))
}

func (bm *BaseMetrics) Meter(name string) metrics.Meter {
	return metrics.NewRegisteredMeter(bm.NameOf(name), bm.Registry)
}

func (bm *BaseMetrics) Timer(name string) metrics.Timer {
	return metrics.NewRegisteredTimer(bm.NameOf(name), bm.Registry)
}

func (bm *BaseMetrics) Gauge(gauge interface{}, name string) {
	bm.Registry.Register(bm.NameOf(name), gauge)
}

type MetricsFactory struct {
	registry metrics.Registry
}

func (mf *MetricsFactory) NewPoolMetrics(baseName string, maxSize int) *PoolMetrics {
	return NewPoolMetrics(mf.registry, baseName, maxSize)
}

// NewMetricsFactory create Metrics Factory
func NewMetricsFactory() *MetricsFactory {
	return &MetricsFactory{
		registry: metrics.NewRegistry(),
	}
}
